package echos

import (
	"net/http"
  //"strings"
	"time";"fmt";"path/filepath";"strconv"
	jwt "github.com/dgrijalva/jwt-go"
	"github.com/labstack/echo"
	//"github.com/labstack/echo/middleware"
)


type RestricUrlCb func(echo.Context) error
type NormalUrlCb func(echo.Context) error

/* 用户验证 Handler
 使用curl发起POST测试请求
 curl -X POST http://172.24.0.244:1323/ApiUserAuth -d 'Username=ljquan;Password=abc1234'
*/
func APP_CbFunc_jsPostUserAuth(c echo.Context) error {
    //获取POST Form, Username;Password的值
    Username := c.FormValue("Username")
    Password := c.FormValue("Password")
    fmt.Println(Username+";"+Password)
   
   	/*
    //实际场景: 需要通过用户名查询redis用户信息, 必须通过密码串核对流程  */
    ccw := connCache()
    AuthStr := ccw.Redis1nd_HashValEject(Username, "Password")
    fmt.Printf("%s\n", AuthStr)
    if AuthStr == "" {
  		return c.JSON(http.StatusOK, echo.Map{
  			"error": "Password nil",
  		})
	  }

    if Password == AuthStr {
		// Set custom claims
		claims := &JwtCustomClaims{
			Username,			
			jwt.StandardClaims{	//token 有效期
				ExpiresAt: time.Now().Add(time.Hour * 10).Unix(),
			},
		}
		// Create token with claims
		token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
		// Generate encoded token and send it as response.
		t, err := token.SignedString(key /*[]byte("secret") */ )
		if err != nil {
			return err
		}
		return c.JSON(http.StatusOK, echo.Map{
			"token": t,
		})
    }
	return echo.ErrUnauthorized
}

/* 浏览器活动注册：在Portal页面提交验证信息
	javascript 函数使用POST 方法提交包含用户名、密码的Form
 */
func APP_HttpClientAction_jsPostAuth_Registry(url string, e *echo.Echo) {
	e.POST(url, APP_CbFunc_jsPostUserAuth)
}

/////////////////////////////////////////////////////////////////////////////////////////////
var (
	// Define a secure key string used
	// as a salt when hashing our tokens.
	// Please make your own way more secure than this,
	// use a randomly generated md5 hash or something.
	key = []byte("mySuperSecretKey")
)

// Decode a token string into a token object
func jwtToken_Decode(tokenString string) (*JwtCustomClaims, error) {

    // Parse the token
    token, err := jwt.ParseWithClaims(tokenString, &JwtCustomClaims{}, func(token *jwt.Token) (interface{}, error) {
        return key, nil
    })

    // Validate the token and return the custom claims
    if claims, ok := token.Claims.(*JwtCustomClaims); ok && token.Valid {
        return claims, nil
    } else {
        return nil, err
    }
}

/* 
  需要token验证的页面 
  1. 第一次登入Portal页面，用户名+密码POST到Server端
  2. Server 端查询用户表，验证通过后，返回token串给Client
  3. Client收到Server返回的token串，成功登录系统，并将token串写入到本地cookie保存
  4. Client后续的应用程序页面访问，每一次都使用GET方法，Client会自动将本地存放的cookie信息发送到Server端
     Server端对于每次的页面访问做cookie解析、token解码，
     确认是有效的token后，返回模板页面，否则返回错误信息页面
 */
func APP_CbFunc_Common(c echo.Context) error {
	//cookie 解析出token   
    token, err := c.Cookie("token")
	if err != nil {
 		return c.String(http.StatusOK, 
 			"You don’t have permission to access this page!\n"+
			"Please login on the Portal page first,\n"+
 			"Then you will get the access token.\n")
	}
	fmt.Printf("GET http-client cookie ->> \n%s: %s\n", 
				token.Name, token.Value)

	//token decode 解码
	claims, token_err := jwtToken_Decode(token.Value)
	fmt.Printf("token user: %s\n", claims.Name)
	fmt.Printf("token error: %v\n", token_err)

	// do something.....
 	if token_err != nil{
 		return c.String(http.StatusOK, 
 			"You don’t have permission to access this page!\n"+
			"Please login on the Portal page first,\n"+
 			"Then you will get the access token.\n")
 	}else {
 		//html页面模板解析
    	templateRef, err := c.Cookie("templateRef")
		if err != nil {
	 		return c.String(http.StatusOK, 
	 			"Web templateRef name parse failed.\n")
		}
		fmt.Printf("GET http-client cookie ->> \n%s: %s\n", 
					templateRef.Name, templateRef.Value)
		//截取template名称，去掉路径信息
		path, template := filepath.Split(templateRef.Value)
		path = path
		//向http client返回页面信息
 		return c.Render(http.StatusOK, template, "")
 	}
}

func APP_Common_URL_Registry(url string, e *echo.Echo) {
	e.GET(url, APP_CbFunc_Common)
}

////////////////////////////////////////////////////////////////////////////////
func APP_Portal_URL_Registry(url string, e *echo.Echo, cb NormalUrlCb) {
	e.GET(url, (echo.HandlerFunc)(cb))
}

/* Portal登录页面, 作为webapp入口, 不需要token验证, 直接返回页面  */
func APP_CbFunc_Portal(c echo.Context) error {
  // do something...
  //指定Portal登录页面的模板名称为【portal】
  return c.Render(http.StatusOK, "portal", "")
  
}


////////////////////////////////////////////////////////////////////////////////
/* Portal注册页面, 不需要token验证, 直接返回页面 */
func APP_CbFunc_Regist(c echo.Context) error {
	// do something...
  //指定Portal注册页面的模板名称为【regist】
  return c.Render(http.StatusOK, "regist", "")
  
}

func APP_CbFunc_jsPostUserRegist(c echo.Context) error {
    //获取POST Form
    Username := c.FormValue("Username")
    Password := c.FormValue("Password")
    Email := c.FormValue("Email")
    Hireyear := c.FormValue("Hireyear")
    fmt.Println(Username+";"+Password+";"+Email+";"+Hireyear)

	//0 表示从字符串形式推断出整型的进制，64 表示返回结果的位数
    y, _ := strconv.ParseInt(Hireyear, 0, 64)

    var Hiredate string
    if y >= 65 || y <= 0 {
    	Hiredate = time.Now().Format("2006-01-02")
    }else{
    	//Hiredate := time.Now().Format("2006-01-02")
    	nowYear := time.Now().Format("2006")
    	Y, _ := strconv.ParseInt(nowYear, 0, 64)
    	Hiredate = strconv.Itoa((int)(Y)-(int)(y))+"-"+time.Now().Format("01-02")
    }
    fmt.Printf("Hiredate: %s\n", Hiredate)

  // do something...
       ccw := connCache()

    NewUser := userinfoHashStruct{
      UserId: strconv.Itoa((int)(APP_TotalNumOfUser_Get(ccw)+1)),
      Username: Username,
      Password: Password,
      Email: Email,
      Hiredate: Hiredate,
      Regtime: time.Now().Format("2006-01-02 15:04:05"),
    }

     retval := ccw.Redis1nd_IsKeyExists(Username)
     if retval == true {
        retstr := fmt.Sprintf("用户名【%s】不可用, 请更换用户名", Username)
        fmt.Printf("%s\n", retstr)
        return c.JSON(http.StatusOK, echo.Map{
          "err": retstr,
        })
     }else{
      //Primary Key-> Username
      APP_registHashValStore(ccw, NewUser, Username)
      APP_TotalNumOfUser_Inc(ccw) //新增用户，redis全局参数TotalNumOfUser加1
      return c.JSON(http.StatusOK, echo.Map{
        "err": "nil",
      })
    }

}

/* 
	浏览器活动注册：在Portal注册页面提交用户信息
	javascript 函数 使用POST 方法提交包含用用户注册信息的Form
 */
func APP_HttpClientAction_jsPostRegist_Registry(url string, e *echo.Echo) {
	e.POST(url, APP_CbFunc_jsPostUserRegist)
}